package com.jimei.common.modules;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanUtils;

/**
 * entity 父类
 *
 * @author czj
 */
public abstract class BaseModel<T extends BaseVO> implements Serializable {
    private static final long serialVersionUID = 1700417739202027815L;
    /**
     * 主键id
     */
    protected Long id;
    /**
     * 逻辑主键pid
     */
    protected String pid;
    protected Date createTime;
    protected Date updateTime;
    /**
     * 默认实体状态
     */
    protected Integer status;
    protected Integer version;

    private Class<T> voClass;
    private static final Map<String, String[]> ignoreFieldMaps = new HashMap<String, String[]>();

    @SuppressWarnings("unchecked")
    public BaseModel() {
        voClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    private String[] ignoreFields() {
        String[] ignoreFields = ignoreFieldMaps.get(getClass().getName());
        if (ignoreFields == null) {
            List<String> hl = new ArrayList<String>();
            Method[] ms = getClass().getDeclaredMethods();
            for (Method m : ms) {
                if (m.getName().startsWith("set")) {
                    Class<?>[] cs = m.getParameterTypes();
                    if (cs.length == 1) {
                        String getName;
                        if (cs[0] == boolean.class) {
                            getName = m.getName().replace("set", "is");
                        } else {
                            getName = "g" + m.getName().substring(1);
                        }
                        Method gm = null;
                        try {
                            gm = voClass.getDeclaredMethod(getName);
                        } catch (NoSuchMethodException e) {
                        }
                        if (gm == null || gm.getReturnType() != cs[0]) {
                            String head = m.getName().substring(3, 4);
                            String tail = m.getName().substring(4);
                            hl.add(head.toLowerCase() + tail);
                        }
                    }
                }
            }
            ignoreFields = new String[hl.size()];
            for (int i = 0; i < hl.size(); i++) {
                ignoreFields[i] = hl.get(i);
            }
            ignoreFieldMaps.put(getClass().getName(), ignoreFields);
        }
        return ignoreFields;
    }

    public T toVO(T vo) {
        try {
            if (vo == null) {
                vo = voClass.newInstance();
            }
            BeanUtils.copyProperties(this, vo, ignoreFields());
//            if (this.createTime != null) {
//                vo.setCreateTime(DateTimeUtil.dateToStr(this.createTime));
//            }
//            if (this.updateTime != null) {
//                vo.setUpdateTime(DateTimeUtil.dateToStr(this.updateTime));
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return vo;
    }


    public void fromVO(T vo) {
        BeanUtils.copyProperties(vo, this);
//        if (StringUtils.isNotEmpty(vo.getCreateTime())) {
//            this.createTime = DateTimeUtil.strToDate(vo.getCreateTime());
//        }
//        if (StringUtils.isNotEmpty(vo.getUpdateTime())) {
//            this.updateTime = DateTimeUtil.strToDate(vo.getUpdateTime());
//        }
    }

    public void fromVO(T vo, String... ignores) {
        BeanUtils.copyProperties(vo, this, ignores);
//        if (StringUtils.isNotEmpty(vo.getCreateTime())) {
//            this.createTime = DateTimeUtil.strToDate(vo.getCreateTime());
//        }
//        if (StringUtils.isNotEmpty(vo.getUpdateTime())) {
//            this.updateTime = DateTimeUtil.strToDate(vo.getUpdateTime());
//        }
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }
}